Break common network code in xen-network-common.sh, and common vif hotplugging
authoremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Fri, 21 Oct 2005 11:06:17 +0000 (12:06 +0100)
committeremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Fri, 21 Oct 2005 11:06:17 +0000 (12:06 +0100)
code into vif-common.sh.

Fix the antispoofing in network-bridge to allow forwarding from physical
device to bridge, and vif0.0 to eth0.

Change the interface between netback driver and vif hotplugging scripts.  The
mac address and bridge details are read from the store directly by the script,
so that the kernel driver does not need to get involved.

Remove an awful lot of cruft from vif-bridge.  Move the iptables handling into
vif-common.sh, and fix it so that the new vif can get past the antispoofing
entries.  Merge vif-nat and vif-route into this structure too.

Use ip instead of ifconfig to get necessary details.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
tools/examples/Makefile
tools/examples/network-bridge [changed mode: 0644->0755]
tools/examples/vif-bridge
tools/examples/vif-common.sh [new file with mode: 0644]
tools/examples/vif-nat
tools/examples/vif-route
tools/examples/xen-hotplug-common.sh
tools/examples/xen-network-common.sh [new file with mode: 0644]

index 6d81bb743363995beab907a07d9474bcfaa58711..f6218fab424ffdd75fb1760f4a9657547f557c13 100644 (file)
@@ -161,34 +161,27 @@ static void backend_changed(struct xenbus_watch *watch,
 static int netback_hotplug(struct xenbus_device *xdev, char **envp,
                           int num_envp, char *buffer, int buffer_size)
 {
-       struct backend_info *be;
-       netif_t *netif;
-       char **key, *val;
+       struct backend_info *be = xdev->data;
+       netif_t *netif = be->netif;
        int i = 0, length = 0;
-       static char *env_vars[] = { "script", "domain", "mac", "bridge", "ip",
-                                   NULL };
 
-       be = xdev->data;
-       netif = be->netif;
+       char *val = xenbus_read(NULL, xdev->nodename, "script", NULL);
+       if (IS_ERR(val)) {
+               int err = PTR_ERR(val);
+               xenbus_dev_error(xdev, err, "reading script");
+               return err;
+       }
+       else {
+               add_hotplug_env_var(envp, num_envp, &i,
+                                   buffer, buffer_size, &length,
+                                   "script=%s", val);
+               kfree(val);
+       }
 
        add_hotplug_env_var(envp, num_envp, &i,
                            buffer, buffer_size, &length,
                            "vif=%s", netif->dev->name);
 
-       key = env_vars;
-       while (*key != NULL) {
-               val = xenbus_read(NULL, xdev->nodename, *key, NULL);
-               if (!IS_ERR(val)) {
-                       char buf[strlen(*key) + 4];
-                       sprintf(buf, "%s=%%s", *key);
-                       add_hotplug_env_var(envp, num_envp, &i,
-                                           buffer, buffer_size, &length,
-                                           buf, val);
-                       kfree(val);
-               }
-               key++;
-       }
-
        envp[i] = NULL;
 
        return 0;
index f94a2224661c8aaf528863c3150a8fb5f6a8ca12..f58f75e0928394684b7322dd183cd67eed036f8a 100644 (file)
@@ -24,7 +24,7 @@ XEN_SCRIPTS += network-route vif-route
 XEN_SCRIPTS += network-nat vif-nat
 XEN_SCRIPTS += block
 XEN_SCRIPTS += block-enbd
-XEN_SCRIPTS += xen-hotplug-common.sh
+XEN_SCRIPTS += xen-hotplug-common.sh xen-network-common.sh vif-common.sh
 
 XEN_HOTPLUG_DIR = /etc/hotplug
 XEN_HOTPLUG_SCRIPTS = xen-backend.agent
old mode 100644 (file)
new mode 100755 (executable)
index 360a651..c9d00b8
@@ -25,7 +25,7 @@
 #            higher value than its default of 1.
 # bridge     The bridge to use (default xenbr${vifnum}).
 # netdev     The interface to add to the bridge (default eth${vifnum}).
-# antispoof  Whether to use iptables to prevent spoofing (default yes).
+# antispoof  Whether to use iptables to prevent spoofing (default no).
 #
 # start:
 # Creates the bridge and enslaves netdev to it.
 #
 #============================================================================
 
-# Gentoo doesn't have ifup/ifdown: define appropriate alternatives
-which ifup >& /dev/null
-if [ "$?" != 0 -a -e /etc/conf.d/net ]; then
-    ifup() {
-        /etc/init.d/net.$1 start
-    }
-    ifdown() {
-        /etc/init.d/net.$1 stop
-    }
-fi
+dir=$(dirname "$0")
+. "$dir/xen-network-common.sh"
 
 # Exit if anything goes wrong.
 set -e 
@@ -66,14 +58,12 @@ for arg ; do export "${arg}" ; done
 vifnum=${vifnum:-0}
 bridge=${bridge:-xenbr${vifnum}}
 netdev=${netdev:-eth${vifnum}}
-antispoof=${antispoof:-yes}
+antispoof=${antispoof:-no}
 
 pdev="p${netdev}"
 vdev="veth${vifnum}"
 vif0="vif0.${vifnum}"
 
-echo "*network $OP bridge=$bridge netdev=$netdev antispoof=$antispoof vifnum=$vifnum" >&2
-
 legacy_mask_to_prefix() {
     mask=$1
     first=${mask%%.*}
@@ -178,15 +168,13 @@ add_to_bridge () {
     fi
 }
 
-# Usage: antispoofing dev bridge
 # Set the default forwarding policy for $dev to drop.
 # Allow forwarding to the bridge.
 antispoofing () {
-    local dev=$1
-    local bridge=$2
-
     iptables -P FORWARD DROP
-    iptables -A FORWARD -m physdev --physdev-in ${dev} -j ACCEPT
+    iptables -F FORWARD
+    iptables -A FORWARD -m physdev --physdev-in ${pdev} -j ACCEPT
+    iptables -A FORWARD -m physdev --physdev-in ${vif0} -j ACCEPT
 }
 
 # Usage: show_status dev bridge
@@ -263,7 +251,7 @@ op_start () {
     fi
 
     if [ ${antispoof} == 'yes' ] ; then
-       antispoofing ${netdev} ${bridge}
+       antispoofing
     fi
 }
 
index 4a947397f469b1f7132245767972946b26d04281..619762fe302ce1a42d375051aeab048ff377aa8b 100755 (executable)
@@ -3,22 +3,19 @@
 # /etc/xen/vif-bridge
 #
 # Script for configuring a vif in bridged mode.
-# Xend calls a vif script when bringing a vif up or down.
-# This script is the default - but it can be configured for each vif.
-#
-# Example invocation:
-#
-# vif-bridge up domain=VM1 vif=vif1.0 bridge=xenbr0 ip="128.232.38.45/28 10.10.10.55/24"
-#
+# The hotplugging system will call this script if it is specified either in
+# the device configuration given to Xend, or the default Xend configuration
+# in /etc/xen/xend-config.sxp.  If the script is specified in neither of those
+# places, then this script is the default.
 #
 # Usage:
-# vif-bridge (up|down) {VAR=VAL}*
+# vif-bridge (up|down)
 #
-# Vars:
+# Environment vars:
+# vif         vif interface name (required).
+# XENBUS_PATH path to this device's details in the XenStore (required).
 #
-# domain  name of the domain the interface is on (required).
-# vif     vif interface name (required).
-# mac     vif MAC address (required).
+# Read from the store:
 # bridge  bridge to add the vif to (required).
 # ip      list of IP networks for the vif, space-separated (optional).
 #
 #============================================================================
 
 dir=$(dirname "$0")
-. "$dir/xen-hotplug-common.sh"
+. "$dir/vif-common.sh"
 
-# Operation name.
-OP=$1
-shift
+bridge=$(xenstore_read "$XENBUS_PATH/bridge")
 
-# Pull variables in args into environment
-for arg ; do export "${arg}" ; done
-
-# Required parameters. Fail if not set.
-domain=${domain:?}
-vif=${vif:?}
-mac=${mac:?}
-bridge=${bridge:?}
+case "$command" in
+    up)
+        if brctl show "$bridge" | grep "$vif" >&/dev/null
+        then
+          log debug "$vif already attached to $bridge"
+          exit 0
+        fi
 
-# Optional parameters. Set defaults.
-ip=${ip:-''}   # default to null (do nothing)
+        brctl addif "$bridge" "$vif" ||
+          fatal "brctl addif $bridge $vif failed"
 
-# Are we going up or down?
-case $OP in
-    up)
-        brcmd='addif'
-        iptcmd='-A'
+        ifconfig "$vif" up || fatal "ifconfig $vif up failed"
         ;;
     down)
-        brcmd='delif'
-        iptcmd='-D'
-        ;;
-    *)
-        echo 'Invalid command: ' $OP >&2
-        echo 'Valid commands are: up, down' >&2
-        exit 1
+        # vifs are auto-removed from bridge.
+        ifconfig "$vif" down || fatal "ifconfig $vif down failed"
         ;;
 esac
 
-# Don't do anything if the bridge is "null".
-if [ "${bridge}" == "null" ] ; then
-    exit
-fi
-
-# Add vif to bridge. vifs are auto-removed from bridge.
-if [ "${brcmd}" == "addif" ] ; then
-    brctl ${brcmd} ${bridge} ${vif}
-fi
-ifconfig ${vif} $OP
-
-if [ "${ip}" ] ; then
-
-    # If we've been given a list of IP networks, allow pkts with these src addrs.
-    for addr in ${ip} ; do
-        iptables ${iptcmd} FORWARD -m physdev --physdev-in ${vif} -s ${addr} -j ACCEPT
-    done 
-
-    # Always allow us to talk to a DHCP server anyhow.
-    iptables ${iptcmd} FORWARD -m physdev --physdev-in ${vif} -p udp --sport 68 --dport 67 -j ACCEPT
-fi
+handle_iptable
 
+log debug "vif-bridge operation for $vif successful."
diff --git a/tools/examples/vif-common.sh b/tools/examples/vif-common.sh
new file mode 100644 (file)
index 0000000..48e3cf9
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Copyright (c) 2005 XenSource Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+
+
+dir=$(dirname "$0")
+. "$dir/xen-hotplug-common.sh"
+. "$dir/xen-network-common.sh"
+
+command="$1"
+
+if [ "$command" != "up" ] && [ "$command" != "down" ]
+then
+  log err "Invalid command: $command"
+  exit 1
+fi
+
+
+XENBUS_PATH="${XENBUS_PATH:?}"
+vif="${vif:?}"
+
+ip=$(xenstore-read "$XENBUS_PATH/ip" >&/dev/null || true)
+
+
+function frob_iptable()
+{
+  if [ "$command" == "up" ]
+  then
+    local c="-A"
+  else
+    local c="-D"
+  fi
+
+  iptables "$c" FORWARD -m physdev --physdev-in "$vif" "$@" -j ACCEPT
+}
+
+
+##
+# Add or remove the appropriate entries in the iptables.  With antispoofing
+# turned on, we have to explicitly allow packets to the interface, regardless
+# of the ip setting.  If ip is set, then we additionally restrict the packets
+# to those coming from the specified networks, though we allow DHCP requests
+# as well.
+#
+function handle_iptable()
+{
+  if [ "$ip" != "" ]
+  then
+      local addr
+      for addr in "$ip"
+      do
+        frob_iptable -s "$addr"
+      done
+
+      # Always allow the domain to talk to a DHCP server.
+      frob_iptable -p udp --sport 68 --dport 67
+  else
+      # No IP addresses have been specified, so allow anything.
+      frob_iptable
+  fi
+}
index a86bd91dd997e41919c0d738e915362c60f57f8c..bf9f40a7b98c0b1c7a495b7c79aee5996fcb48be 100644 (file)
@@ -3,40 +3,30 @@
 # /etc/xen/vif-nat
 #
 # Script for configuring a vif in routed-nat mode.
-# Xend calls a vif script when bringing a vif up or down.
-# This script is the default - but it can be configured for each vif.
-#
-# Example invocation:
-#
-# vif-nat up domain=VM1 vif=vif1.0 ip="192.168.0.10/31"
+# The hotplugging system will call this script if it is specified either in
+# the device configuration given to Xend, or the default Xend configuration
+# in /etc/xen/xend-config.sxp.  If the script is specified in neither of those
+# places, then vif-bridge is the default.
 #
 # Usage:
-# vif-nat (up|down) {VAR=VAL}*
+# vif-nat (up|down)
 #
-# Vars:
+# Environment vars:
+# vif         vif interface name (required).
+# XENBUS_PATH path to this device's details in the XenStore (required).
 #
-# domain  name of the domain the interface is on (required).
-# vif     vif interface name (required).
-# ip      list of IP networks for the vif, space-separated (required).
+# Read from the store:
+# ip      list of IP networks for the vif, space-separated (default given in
+#         this script).
 #============================================================================
 
-# Exit if anything goes wrong
-set -e 
-export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH
-
-# Operation name.
-OP=$1
-shift
-
-# Pull variables in args into environment
-for arg ; do export "${arg}" ; done
+dir=$(dirname "$0")
+. "$dir/vif-common.sh"
 
-# Required parameters. Fail if not set.
-domain=${domain:?}
-vif=${vif:?}
-ip=${ip:-'169.254.1.1/24'}   #if not defined, give a default address 
-
-echo "*vif-nat $OP domain=$domain vif=$vif ip=$ip" >&2
+if [ "$ip" == "" ]
+then
+  ip='169.254.1.1/24'
+fi
 
 #determine ip address and netmask 
 vif_ip=`echo ${ip} | awk -F/ '{print $1}'`
@@ -47,27 +37,20 @@ netmask=$netmask.$(( (($intmask & 0x00FF0000)) >> 16 ))
 netmask=$netmask.$(( (($intmask & 0x0000FF00)) >> 8 ))
 netmask=$netmask.$(( $intmask & 0x000000FF ))
 
-main_ip=`ifconfig eth0 | grep "inet addr:" | sed -e 's/.*inet addr:\(\w\w*\.\w\w*\.\w\w*\.\w\w*\).*/\1/'`
+main_ip=$(ip addr show eth0 | sed -e '/inet /!d;s/^.*inet \([^\s*]\)\s.*$/\1/')
 
-# Are we going up or down?
-case $OP in
+case "$command" in
     up)
         ifconfig ${vif} ${vif_ip} netmask ${netmask} up
         echo 1 >/proc/sys/net/ipv4/conf/${vif}/proxy_arp
-        iptcmd='-A'
         ipcmd='a'
         ;;
     down)
         ifconfig ${vif} down
-        iptcmd='-D'
         ipcmd='d'
         ;;
-    *)
-        echo 'Invalid command: ' $OP >&2
-        echo 'Valid commands are: up, down' >&2
-        exit 1
-        ;;
 esac
 
 ip r ${ipcmd} ${ip} dev ${vif} src ${main_ip}
-#    iptables ${iptcmd} FORWARD -m physdev --physdev-in ${vif} -p udp --sport 68 --dport 67 -j ACCEPT
+
+handle_iptable()
index efb83881d226127c5c14b814c7fdec2d6d2e99f2..beb8e43ef212cfc4adfa5b45fc7f91135be29701 100755 (executable)
@@ -3,74 +3,46 @@
 # /etc/xen/vif-route
 #
 # Script for configuring a vif in routed mode.
-# Xend calls a vif script when bringing a vif up or down.
-# This script is the default - but it can be configured for each vif.
-#
-# Example invocation:
-#
-# vif-route up domain=VM1 vif=vif1.0 ip="128.232.38.45/28 10.10.10.55/24"
+# The hotplugging system will call this script if it is specified either in
+# the device configuration given to Xend, or the default Xend configuration
+# in /etc/xen/xend-config.sxp.  If the script is specified in neither of those
+# places, then vif-bridge is the default.
 #
 # Usage:
-# vif-route (up|down) {VAR=VAL}*
+# vif-route (up|down)
 #
-# Vars:
+# Environment vars:
+# vif         vif interface name (required).
+# XENBUS_PATH path to this device's details in the XenStore (required).
 #
-# domain  name of the domain the interface is on (required).
-# vif     vif interface name (required).
-# mac     vif MAC address (required).
-# ip      list of IP networks for the vif, space-separated (optional).
+# Read from the store:
+# ip      list of IP networks for the vif, space-separated (default given in
+#         this script).
 #============================================================================
 
-# Exit if anything goes wrong
-set -e 
-export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH
-echo "*vif-route $*" >&2
-
-# Operation name.
-OP=$1
-shift
-
-# Pull variables in args into environment
-for arg ; do export "${arg}" ; done
-
-# Required parameters. Fail if not set.
-domain=${domain:?}
-vif=${vif:?}
-mac=${mac:?}
+dir=$(dirname "$0")
+. "$dir/vif-common.sh"
 
-# Optional parameters. Set defaults.
-ip=${ip:-''}   # default to null (do nothing)
+main_ip=$(ip addr show eth0 | sed -e '/inet /!d;s/^.*inet \([^\s*]\)\s.*$/\1/')
 
-main_ip=`ifconfig eth0 | grep "inet addr:" | sed -e 's/.*inet addr:\(\w\w*\.\w\w*\.\w\w*\.\w\w*\).*/\1/'`
-
-# Are we going up or down?
-case $OP in
+case "$command" in
     up)
-        ifconfig ${vif} 169.254.1.0 netmask 255.255.255.255 up
+        ifconfig ${vif} ${main_ip} netmask 255.255.255.255 up
         echo 1 >/proc/sys/net/ipv4/conf/${vif}/proxy_arp
-        iptcmd='-A'
         ipcmd='a'
         ;;
     down)
-        ifconfig ${vif} down
-        iptcmd='-D'
+        ifdown ${vif}
         ipcmd='d'
         ;;
-    *)
-        echo 'Invalid command: ' $OP >&2
-        echo 'Valid commands are: up, down' >&2
-        exit 1
-        ;;
 esac
 
 if [ "${ip}" ] ; then
-
-    # If we've been given a list of IP networks, allow pkts with these src addrs.
+    # If we've been given a list of IP addresses, then add routes from dom0 to
+    # the guest using those addresses.
     for addr in ${ip} ; do
       ip r ${ipcmd} ${addr} dev ${vif} src ${main_ip}
-#      iptables ${iptcmd} FORWARD -m physdev --physdev-in ${vif} -s ${addr} -j ACCEPT
     done 
-
-    # Always allow us to talk to a DHCP server anyhow.
-#    iptables ${iptcmd} FORWARD -m physdev --physdev-in ${vif} -p udp --sport 68 --dport 67 -j ACCEPT
 fi
+
+handle_iptable()
index 10c7d4c87b37260efb4ee46b3bed00ceb229b9cb..c25f493551e15b39acbd8f7ce02b47767e5a1ebd 100644 (file)
@@ -10,19 +10,20 @@ log() {
   logger -p "daemon.$level" -- "$0:" "$@" || echo "$0 $@" >&2
 }
 
+fatal() {
+  log err "$@"
+  exit 1
+}
+
 xenstore_read() {
   local v=$(xenstore-read "$@" || true)
-  if [ "$v" == "" ]
-  then
-    log error "xenstore-read $@ failed."
-    exit 1
-  fi
+  [ "$v" != "" ] || fatal "xenstore-read $@ failed."
   echo "$v"
 }
 
 xenstore_write() {
   log debug "Writing $@ to xenstore."
-  xenstore-write "$@" || log error "Writing $@ to xenstore failed."
+  xenstore-write "$@" || log err "Writing $@ to xenstore failed."
 }
 
 log debug "$@" "XENBUS_PATH=$XENBUS_PATH"
diff --git a/tools/examples/xen-network-common.sh b/tools/examples/xen-network-common.sh
new file mode 100644 (file)
index 0000000..d4af399
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2005 XenSource Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+
+
+# Gentoo doesn't have ifup/ifdown: define appropriate alternatives
+if ! which ifup >&/dev/null
+then
+  if [ -e /etc/conf.d/net ]
+  then
+    ifup()
+    {
+      /etc/init.d/net.$1 start
+    }
+    ifdown()
+    {
+      /etc/init.d/net.$1 stop
+    }
+  else
+    logger -p "daemon.crit" -- \
+      "You don't have ifup and don't seem to be running Gentoo either!"
+    exit 1
+  fi
+fi